package com.bupt.service.common.impl;


import com.bupt.Factory.ProjectFactory;
import com.bupt.base.ExcelProcedure;
import com.bupt.basic.BasicNetWork;
import com.bupt.basic.DemandReportService;
import com.bupt.basic.IBasicNetWork;
import com.bupt.basic.Project;
import com.bupt.config.interceptor.thread.CurrentUserInfo;
import com.bupt.constants.InitConstants;

import com.bupt.dto.network.*;
import com.bupt.dto.service.ServiceDto;
import com.bupt.dto.sys.LoginUserDto;
import com.bupt.dto.sys.UserDto;
import com.bupt.entity.*;
import com.bupt.exception.BaseException;

import com.bupt.service.common.LinkService;
import com.bupt.service.common.WordAndExcelExportService;
import com.bupt.utils.GenerateIDUtils;
import com.bupt.utils.LinkStatusString;
import com.bupt.utils.LocalVerify;
import com.bupt.utils.TypeString;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * word and excel 下载的模版
 *
 * @author breakpoint/赵先生
 * create on 2020/10/29
 */
@Service
public class WordAndExcelExportServiceImpl implements WordAndExcelExportService, ExcelProcedure {
    //锁信息
    private static final Object lock = new Object(); // 锁信息

    @Resource
    private LinkService linkService;

    @Resource
    private CurrentUserInfo userInfo;
    
    private static final String successListKey = "successList"; // 成功的列表
    private static final String failListKey = "failList"; //失败的列表



    @Override
    public Object downLoadNodeMould(HttpServletRequest request, HttpServletResponse response) throws BaseException {
        List<BasicNetWork.BasicNode> list = new ArrayList<>();
        // 下载模版专用的

        list.add(new BasicNetWork.BasicNode("例子：1", "北京", "n202020",
                116.367188, 39.909736, 2020, 2021, 10,100));
        downLoadExcel(request, response, list, "节点导入模版", "sheet1", true);
        return InitConstants.OK_MESSAGE;
    }


    // 下载fiber链路的模板的操作
    @Override
    public Object downLoadFiberLinkMould(HttpServletRequest request,
                                         HttpServletResponse response) throws BaseException {
        IBasicNetWork.BasicLink fiberLink = new BasicNetWork.FiberLink(
                "链路ID", "FIBER",
                "N20201112", "北京-上海", "北京-上海",
                "北京",null,
                "上海",null, false, 2020,
                "system", "system", new Date(),
                10L, "地缆", 1000L,
                "华北",
                "中国电信", 0.2, "光缆型号", "光缆情况", 10L, 10, 10, 0.2
        );
        downLoadExcel(request, response, Collections.singletonList(fiberLink),
                "FIBER链路模板", "Sheet1", true);
        return InitConstants.OK_MESSAGE;
    }


    // 下载wdm链路的模板的操作
    @Override
    public Object downLoadWdmLinkMould(HttpServletRequest request,
                                       HttpServletResponse response) throws BaseException {
        BasicNetWork.WdmLink wdmLink = new BasicNetWork.WdmLink(
                "链路ID",
                "WDM", "N20201212", "北京-上海", "北京-上海",
                "北京",null,
                "上海",null, false, 2020,
                "system", "system", new Date(), 10L,
                "GE", "FIBER", 10L
        );
        downLoadExcel(request, response, Collections.singletonList(wdmLink),
                "WDM链路模板", "Sheet1", true);
        return InitConstants.OK_MESSAGE;
    }

    @Override
    public Object downLoadOtnLinkMould(HttpServletRequest request,
                                       HttpServletResponse response) throws BaseException {
        BasicNetWork.OtnLink otnLink = new BasicNetWork.OtnLink(
                "链路ID", "OTN", "N20201109", "北京-上海", "北京-上海",
                "北京",null, "上海",null, false, 2020, "system", "system",
                new Date(), "FIBER", 1L, "100G", 10L
        );
        downLoadExcel(request, response, Collections.singletonList(otnLink),
                "OTN链路模板", "Sheet1", true);
        return InitConstants.OK_MESSAGE;
    }

    @Override
    public Object downLoadSdhLinkMould(HttpServletRequest request,
                                       HttpServletResponse response) throws BaseException {
        BasicNetWork.SdhLink sdhLink = new BasicNetWork.SdhLink(
                "链路ID", "SDH", "N2020111222",
                "北京-上海", "北京-上海",
                "北京",null,
                "上海", null,false, 2020,
                "system", "system", new Date(), "2.5G", "WDM",
                10L, 10L
        );
        downLoadExcel(request, response, Collections.singletonList(sdhLink),
                "SDH链路模板", "Sheet1", true);
        return InitConstants.OK_MESSAGE;
    }

    @Override
    public Object upLoadFiberLinkFileToProject(UserDto userDto, String pId, MultipartFile file) throws BaseException {
        userDto = userInfo.getCurrentOptUser();
        List<BasicNetWork.FiberLink> fiberLinks =
                parseExcelDataFromExcelInputStream(file, BasicNetWork.FiberLink.class);
        Project project = ProjectFactory.getObjectFromFile(pId, ProjectFactory.storePath);
        BasicNetWork basicNetWork=project.getBasicNetWork();
        Map<String, List<AddLinkDto>> map = addLinksToBasicNetwork(userDto, project, fiberLinks, false);
        List<AddLinkDto> success = map.get(successListKey);
        List<AddLinkDto> fail= map.get(failListKey);
        //新增fiber链路的返回
        List<FiberDto> successList=new ArrayList<>();

        for (AddLinkDto addLinkDto : success) {
            IBasicNetWork.BasicLink link = addLinkDto.link;
            IBasicNetWork.FiberLink f = (IBasicNetWork.FiberLink) link;
            FiberLinkDto fiberLinkDto = new FiberLinkDto(f.getId(), f.getName(), f.getCode(), f.getSourceNode(), f.getTargetNode(), f.getYear(), f.getServiceLength(), f.getLength(), f.getXxsl(), f.getAsfs(),
                    f.getFaultTime(), f.getAveAttenua().doubleValue(), f.getXxsh());
          successList.add(new FiberDto(fiberLinkDto,addLinkDto.reason));

        }
        ArrayList<FiberDto> failList = new ArrayList<>();
        for (AddLinkDto addLinkDto : fail) {
            IBasicNetWork.BasicLink link = addLinkDto.link;
            IBasicNetWork.FiberLink f = (IBasicNetWork.FiberLink) link;
            FiberLinkDto fiberLinkDto = new FiberLinkDto(f.getId(), f.getName(), f.getCode(), f.getSourceNode(), f.getTargetNode(), f.getYear(), f.getServiceLength(), f.getLength(), f.getXxsl(), f.getAsfs(),
                    f.getFaultTime(), f.getAveAttenua().doubleValue(), f.getXxsh());
            failList.add(new FiberDto(fiberLinkDto,addLinkDto.reason));
        }
        HashMap<String, List<FiberDto>> resultMap = new HashMap<>();
        resultMap.put(successListKey,successList);
        resultMap.put(failListKey,failList);
        return resultMap;

    }

    @Override
    public Object upLoadWdmLinkFileToProject(UserDto userDto, MultipartFile file, String pId) throws BaseException {
        userDto = userInfo.getCurrentOptUser();
        List<IBasicNetWork.WdmLink> wdmLinks =
                parseExcelDataFromExcelInputStream(file, IBasicNetWork.WdmLink.class);
        Project project = ProjectFactory.getObjectFromFile(pId, ProjectFactory.storePath);
        Map<String, List<AddLinkDto>> map = addLinksToBasicNetwork(userDto, project, wdmLinks, false);
        List<AddLinkDto> success = map.get(successListKey);
        List<AddLinkDto> fail = map.get(failListKey);
        List<WdmDto> successList= new ArrayList<>();
        List<WdmDto> failList=new ArrayList<>();
        for (AddLinkDto addLinkDto : success) {
            IBasicNetWork.WdmLink link = (IBasicNetWork.WdmLink) addLinkDto.link;
            WdmLinkDto wdmLinkDto = new WdmLinkDto(link.getId(), link.getName(), link.getCode(), link.getSourceNode(), link.getTargetNode(), link.getLength(), link.getYear(), link.getSize(), link.getRateStr(),link.getBaseLinkIds(),link.getBaseLinkNames());
            successList.add(new WdmDto(wdmLinkDto,addLinkDto.reason));
        }
        for (AddLinkDto addLinkDto : fail) {
            IBasicNetWork.WdmLink link = (IBasicNetWork.WdmLink) addLinkDto.link;
            WdmLinkDto wdmLinkDto = new WdmLinkDto(link.getId(), link.getName(), link.getCode(), link.getSourceNode(), link.getTargetNode(), link.getLength(), link.getYear(), link.getSize(), link.getRateStr(),link.getBaseLinkIds(),link.getBaseLinkNames());
           failList.add(new WdmDto(wdmLinkDto,addLinkDto.reason));
        }
        HashMap<String, List<WdmDto>> resultMap = new HashMap<>();
        resultMap.put(successListKey,successList);
        resultMap.put(failListKey,failList);
        return resultMap;
    }

    @Override
    public Object upLoadOtnLinkFileToProject(UserDto userDto, MultipartFile file, String pId) throws BaseException {
        userDto = userInfo.getCurrentOptUser();
        List<IBasicNetWork.OtnLink> otnLinks =
                parseExcelDataFromExcelInputStream(file, IBasicNetWork.OtnLink.class);
        Project project = ProjectFactory.getObjectFromFile(pId, ProjectFactory.storePath);
        Map<String, List<AddLinkDto>> map = addLinksToBasicNetwork(userDto, project, otnLinks, false);
        List<AddLinkDto> success = map.get(successListKey);
        List<AddLinkDto> fail = map.get(failListKey);
        List<OtnDto> successList= new ArrayList<>();
        List<OtnDto> failList=new ArrayList<>();
        for (AddLinkDto addLinkDto : success) {
            IBasicNetWork.OtnLink link = (IBasicNetWork.OtnLink) addLinkDto.link;
            OtnLinkDto otnLinkDto = new OtnLinkDto(link.getId(), link.getName(), link.getCode(), link.getSourceNode(), link.getTargetNode(), link.getLength(), link.getYear(), link.getSize(), link.getRateStr(),link.getLoadOnLayer());
            successList.add(new OtnDto(otnLinkDto,addLinkDto.reason));
        }
        for (AddLinkDto addLinkDto : fail) {
            IBasicNetWork.OtnLink link = (IBasicNetWork.OtnLink) addLinkDto.link;
            OtnLinkDto otnLinkDto = new OtnLinkDto(link.getId(), link.getName(), link.getCode(), link.getSourceNode(), link.getTargetNode(), link.getLength(), link.getYear(), link.getSize(), link.getRateStr(),link.getLoadOnLayer());
            failList.add(new OtnDto(otnLinkDto,addLinkDto.reason));
        }
        HashMap<String, List<OtnDto>> resultMap = new HashMap<>();
        resultMap.put(successListKey,successList);
        resultMap.put(failListKey,failList);
        return resultMap;
    }

    @Override
    public Object upLoadSdhLinkFileToProject(UserDto userDto, MultipartFile file, String pId) throws BaseException {
        userDto = userInfo.getCurrentOptUser();
        List<IBasicNetWork.SdhLink> sdhLinks =
                parseExcelDataFromExcelInputStream(file, IBasicNetWork.SdhLink.class);
        Project project = ProjectFactory.getObjectFromFile(pId, ProjectFactory.storePath);
        Map<String, List<AddLinkDto>> map = addLinksToBasicNetwork(userDto, project, sdhLinks, false);
        List<AddLinkDto> success = map.get(successListKey);
        List<AddLinkDto> fail = map.get(failListKey);
        List<SdhDto> successList= new ArrayList<>();
        List<SdhDto> failList=new ArrayList<>();
        for (AddLinkDto addLinkDto : success) {
            IBasicNetWork.SdhLink link = (IBasicNetWork.SdhLink) addLinkDto.link;
            SdhLinkDto sdhLinkDto = new SdhLinkDto(link.getId(), link.getName(), link.getCode(), link.getSourceNode(), link.getTargetNode(), link.getLength(), link.getYear(), link.getRateStr(),link.getLoadOnLayer());
            successList.add(new SdhDto(sdhLinkDto,addLinkDto.reason));
        }
        for (AddLinkDto addLinkDto : fail) {
            IBasicNetWork.SdhLink link = (IBasicNetWork.SdhLink) addLinkDto.link;
            SdhLinkDto sdhLinkDto = new SdhLinkDto(link.getId(), link.getName(), link.getCode(), link.getSourceNode(), link.getTargetNode(), link.getLength(), link.getYear(), link.getRateStr(),link.getLoadOnLayer());
            failList.add(new SdhDto(sdhLinkDto,addLinkDto.reason));
        }
        HashMap<String, List<SdhDto>> resultMap = new HashMap<>();
        resultMap.put(successListKey,successList);
        resultMap.put(failListKey,failList);
        return resultMap;
    }

    @Override
    public Object downLoadDemandMould(UserDto userDto, HttpServletRequest request, HttpServletResponse response) throws BaseException {
        DemandReportService service = new DemandReportService("1", "北京到兰州业务", "北京",
                "兰州", "IP", 100.0, "", "SDH", 2020, new Date(),
                "system", "system");
       downLoadExcel(request, response, Collections.singletonList(service),
                "业务导入模板", "Sheet1", true);
        return InitConstants.OK_MESSAGE;
    }

    @Override
    public Object upLoadDemandToProject(UserDto userDto, String pId, MultipartFile file) throws BaseException {
        userDto = userInfo.getCurrentOptUser();
        List<DemandReportService> services =
               parseExcelDataFromExcelInputStream(file, DemandReportService.class);
        return  addServices(userDto, pId, services);
    }

    public Map<String, List<AddServiceDto>> addServices(UserDto userDto, String pId,
                                                        final List<DemandReportService> serviceList)
            throws BaseException {
        LocalVerify.verifyString(pId, "项目的ID");
        if (null == serviceList || serviceList.size() == 0) throw new BaseException("至少有一个业务");
        Project project = ProjectFactory.getObjectFromFile(pId, ProjectFactory.storePath);

         BasicNetWork netWork = project.getBasicNetWork(); // get current project network
        List<DemandReportService> demandList = project.getDemandList();//得到当前的业务列表
        Set<String> nameSet= new HashSet<>();
        for (DemandReportService demandReportService : demandList) {
            nameSet.add(demandReportService.getName());
        }

        if (null == netWork) throw new BaseException("当前没有网络信息，添加失败");
            synchronized (lock) {
                // 成功失败的list
                List<AddServiceDto> successList = new ArrayList<AddServiceDto>();
                List<AddServiceDto> failList = new ArrayList<AddServiceDto>();

                for (DemandReportService service : serviceList) {
                    String nodeHeadId="";
                    String nodeTailId="";
                    try {
                        LocalVerify.verifyString(service.getName(), "业务名字");
                        LocalVerify.verifyString(service.getNodeHead(), "业务头节点");
                        LocalVerify.verifyString(service.getNodeTail(), "业务尾节点");
                        LocalVerify.verifyString(service.getBandwidth(), "需求带宽");
                        LocalVerify.verifyString(service.getLayer(), "所属层级");
                        LocalVerify.verifyString(service.getType(), "需求类型");
                        LocalVerify.verifyString(service.getProtect(), "业务保护等级");
                        if (service.getProtectLimit() == null || service.getProtectLimit() <= 0)
                            throw new BaseException("业务保护跳数需要大于0");

                        if (service.getNodeHead().equals(service.getNodeTail()))
                            throw new BaseException("业务的头尾节点不能相同");
                        // 校验基础的信息
                        if(nameSet.contains(service.getName()))throw new BaseException("业务名字重复");
                        try {
                             nodeHeadId = netWork.getNodeId(service.getNodeHead());
                            service.setNodeHead(nodeHeadId);
                        } catch (Exception e) {
                            throw new BaseException("【" + service.getName() + "】业务的 开始节点不存在");
                        }
                        try {
                            nodeTailId = netWork.getNodeId(service.getNodeTail());
                            service.setNodeTail(nodeTailId);
                        } catch (Exception e) {
                            throw new BaseException("【" + service.getName() + "】业务的 结束节点不存在");
                        }

                        // 设置业务的ID 的信息
                        if (null == service.getId()) {
                            service.setId(UUID.randomUUID().toString().substring(0,12));
                        }
                        // 设置节点的名字
                        service.setNodeHeadName(netWork.getNodeName(service.getNodeHead()));
                        service.setNodeTailName(netWork.getNodeName(service.getNodeTail()));
                        // 设置基本信息
                        service.setCreateUserId(userDto.getUId());
                        service.setCreateUserName(userDto.getUserName());
                        service.setGmtCreate(new Date());
                        service.setProtectName(service.getProtect());
                        // 添加业务的信息操作
                        demandList.add(service);
                        // 记录添加的结果
                        List<Node> node = getNode(nodeHeadId, nodeTailId, project);
                        node.get(0).setName(service.getNodeHeadName());
                        node.get(1).setName(service.getNodeTailName());
                        ServiceDto serviceDto = new ServiceDto(service.getId(), service.getName(), node.get(0), node.get(1), service.getYear(), service.getBandwidthNum(), service.getType(),
                                service.getLayer(), service.getProtect(), service.getProtectLimit(), "".split(","), service.getStatus(), service.getReason());
                        successList.add(new AddServiceDto(serviceDto, "添加成功"));
                    } catch (Exception e) {
                        List<Node> node = getNode(nodeHeadId, nodeTailId, project);
                        node.get(0).setName(service.getNodeHeadName());
                        node.get(1).setName(service.getNodeTailName());
                        ServiceDto serviceDto = new ServiceDto(service.getId(), service.getName(), node.get(0), node.get(1), service.getYear(), service.getBandwidthNum(), service.getType(),
                                service.getLayer(), service.getProtect(), service.getProtectLimit(), "".split(","), service.getStatus(), service.getReason());
                        failList.add(new AddServiceDto(serviceDto, e.getMessage()));
                    }
                }
                // end for
                //更新业务信息至项目
                updateProject(project);
                Map<String, List<AddServiceDto>> res = new HashMap<>();
                res.put(successListKey, successList);
                res.put(failListKey, failList);
                return res;
            }
        }



    // 上传新建节点
    @Override
    public Object upLoadNodeFileToProject(UserDto userDto,HttpServletRequest request, String projectId, MultipartFile file) throws BaseException {
         userDto = userInfo.getCurrentOptUser();
        LocalVerify.verifyString(projectId, "项目ID");
        if (ProjectFactory.getObjectFromFile(projectId, ProjectFactory.storePath) == null)
            throw new BaseException("此项目不存在");
        // 解析上传过来的文件
        List<BasicNetWork.BasicNode> list = parseExcelDataFromExcelInputStream(file, BasicNetWork.BasicNode.class);
        // 将节点的信息增加到项目中
        Map<String, List<AddNodeDto>> map= addNodeToNetWork(userDto, request, projectId, list);
        List<AddNodeDto> success = map.get(successListKey);
        List<AddNodeDto> fail = map.get(failListKey);
        List<BasicNodeDto> successList= new ArrayList<>();
        List<BasicNodeDto> failList=new ArrayList<>();
        for (AddNodeDto addNodeDto : success) {
            IBasicNetWork.BasicNode commonNode = addNodeDto.node;
            NodeDto nodeDto = new NodeDto(commonNode.getNodeId(), commonNode.getName(), commonNode.getCode(), commonNode.getPointX(), commonNode.getPointY(), commonNode.getYear(), commonNode.getCompletedYear(), commonNode.getServiceLength(), commonNode.getCapacity());
            successList.add(new BasicNodeDto(nodeDto,addNodeDto.reason));
        }
        for (AddNodeDto addNodeDto : fail) {
            IBasicNetWork.BasicNode commonNode = addNodeDto.node;
            NodeDto nodeDto = new NodeDto(commonNode.getNodeId(), commonNode.getName(), commonNode.getCode(), commonNode.getPointX(), commonNode.getPointY(), commonNode.getYear(), commonNode.getCompletedYear(), commonNode.getServiceLength(),
                    commonNode.getCapacity());
            failList.add(new BasicNodeDto(nodeDto,addNodeDto.reason));
        }
        HashMap<String, List<BasicNodeDto>> resultMap = new HashMap<>();
        resultMap.put(successListKey,successList);
        resultMap.put(failListKey,failList);
        return resultMap;
    }

    public Map<String, List<AddNodeDto>> addNodeToNetWork(UserDto userDto,HttpServletRequest request, String projectId, List<BasicNetWork.BasicNode> nodes)
            throws BaseException {
        userDto = userInfo.getCurrentOptUser();
        if (null != nodes && nodes.size() > 0) {
            synchronized (lock) {
                // 设置返回的值
                List<AddNodeDto> successList = new ArrayList<AddNodeDto>();
                List<AddNodeDto> failList = new ArrayList<AddNodeDto>();
                // 获取当前系统网络的基础文件
                Project project = ProjectFactory.getObjectFromFile(projectId, ProjectFactory.storePath);
                BasicNetWork basicNetWork = project.getBasicNetWork();
                for (BasicNetWork.BasicNode node : nodes) {
                    try {
                        LocalVerify.verifyString(node.getName(), "节点名称");
                        LocalVerify.verifyString(node.getCode(), "节点编码");
                     /*   LocalVerify.verifyString(node.getManager(), "负责人");
                        LocalVerify.verifyString(node.getManagerPhone(), "负责电话");*/
                        if (node.getPointX() == null) throw new BaseException("经度必填");
                        if (node.getPointY() == null) throw new BaseException("纬度必填");
                        if (node.getYear() == null) throw new BaseException("开通年份必填");
                        // 当前的基础网络是存在当前的节点的信息的，那么就应该进行导入的操作
                        if (basicNetWork.getNodeNameSet().contains(node.getName()))
                            throw new BaseException("基础网络文件存在【" + node.getName() + "】节点，请进行导入节点操作");
                        // 设置节点的信息
                        // 采用hashCOde 来保证
                        node.setNodeId(String.valueOf(node.getName().hashCode()));
                        Date nowTime = new Date();
                        node.setCreateDate(nowTime);
                        if(userDto==null)throw new BaseException("您还未登录，请先登录");
                        node.setCreateId(userDto.getUId());
                        node.setCreateName(userDto.getUserName());
                        node.setIsOrigin(false);
                        // 基础网络添加节点操作 issue
                        basicNetWork.addNode(node);
                        successList.add(new AddNodeDto(node, "添加成功"));
                    } catch (Exception e) {
                        failList.add(new AddNodeDto(node, e.getMessage()));
                    }
                }// for (BasicNetWork.BasicNode node : nodes)
                // 返回操作
                Map<String, List<AddNodeDto>> res = new HashMap<>();
                res.put(successListKey, successList);
                res.put(failListKey, failList);
                // 更新网络信息至项目
               updateProject(project);
                return res;
            }
        } else {
            //// if (null != nodes && nodes.size() > 0)
            throw new BaseException("至少有一个节点");
        }
    }

    public Map<String, List<AddLinkDto>> addLinksToBasicNetwork(UserDto userDto,
                                                                Project project,
                                                                List<? extends BasicNetWork.BasicLink> links,
                                                                boolean isOrigin) throws BaseException {
        userDto = userInfo.getCurrentOptUser();
        // 得到链路的类别的操作
        Map<Class<?>, BasicNetWork.LayerEnum> clazzToIntegerMap = BasicNetWork.clazzToIntegerMap;
        // 成功以及失败的list
        List<AddLinkDto> successList = new ArrayList<>();
        List<AddLinkDto> failList = new ArrayList<>();
        synchronized (lock) {
            BasicNetWork basicNetWork = project.getBasicNetWork();
            if (null != links && links.size() > 0) {
                // 循环处理链路的信息
                for (BasicNetWork.BasicLink link : links) {
                    try {
                        // 初始化 基本信息
                        if (!isOrigin) {
                            if(userDto==null)throw new BaseException("您还未登录，请先登录");
                            if(userDto!=null) {
                                link.setCreateId(userDto.getUId());
                                link.setCreateName(userDto.getUserName());
                            }
                            link.setCreateTime(new Date());
                        }
                        // 设置ID的操作
                        // 进行修改成同一个的操作
                        if (null == link.getId() || "".equals(link.getId())) {
                            link.setId(GenerateIDUtils.generateIdStr());
                        }
                        LocalVerify.verifyString(link.getCode(), "【" + link.getName() + "】链路编码");
                        LocalVerify.verifyString(link.getName(), "链路名称");
                        LocalVerify.verifyString(link.getNodeHead(), "【" + link.getName() + "】链路头节点");
                        LocalVerify.verifyString(link.getNodeTail(), "【" + link.getName() + "】链路尾节点");
                        if (null == link.getYear()) throw new BaseException("【" + link.getName() + "】竣工年份必填");
                        try {
                            String nodeId = basicNetWork.getNodeId(link.getNodeHead());
                            link.setNodeHead(nodeId);
                            link.setNodeHeadName(basicNetWork.getNodeName(nodeId));
                        } catch (Exception e) {
                            throw new BaseException("【" + link.getName() + "】链路头节点不存在");
                        }
                        try {
                            String nodeId = basicNetWork.getNodeId(link.getNodeTail());
                            link.setNodeTail(nodeId);
                            link.setNodeTailName(basicNetWork.getNodeName(nodeId));
                        } catch (Exception e) {
                            throw new BaseException("【" + link.getName() + "】链路尾节点不存在");
                        }
                        link.setLayer("FIBER");
                        if (link instanceof BasicNetWork.WdmLink) {
                            addOperationBaseIsFiber(basicNetWork,link);
                            link.setLayer("WDM");
                        }

                        if(link instanceof BasicNetWork.OtnLink){
                            BasicNetWork.OtnLink otnLink = (BasicNetWork.OtnLink) link;
                            switch (otnLink.getLoadOnLayer()){
                                case "FIBER":
                                    addOperationBaseIsFiber(basicNetWork,link);
                                    link.setLayer("OTN");
                                    break;
                                case  "WDM":
                                    addOperationBaseIsWdm(basicNetWork,link);
                                    link.setLayer("OTN");
                                    break;
                                default:
                                    System.out.println("OTN找不到承载层，链路导入失败");
                            }
                        }

                        if(link instanceof BasicNetWork.SdhLink){
                            BasicNetWork.SdhLink SdhLink = (BasicNetWork.SdhLink) link;
                            switch (SdhLink.getLoadOnLayer()){
                                case "FIBER":
                                    addOperationBaseIsFiber(basicNetWork,link);
                                    link.setLayer("SDH");
                                    break;
                                case "WDM":
                                    addOperationBaseIsWdm(basicNetWork,link);
                                    link.setLayer("SDH");
                                    break;
                                case "OTN":
                                    addOperationBaseIsOtn(basicNetWork,link);
                                    link.setLayer("SDH");
                                    break;
                                default:
                                    System.out.println("sdh找不到承载层，链路导入失败");

                            }
                            link.setLayer("SDH");
                        }

                        Map<String,List<IBasicNetWork.PortL>> portsMap=basicNetWork.getPorts();
                        // 校验基础的数据
                        if (linkService.preCheckLinkMsg(userDto, basicNetWork, link, clazzToIntegerMap.get(link.getClass()))) {
                            // 增加链路信息
                            link.setLabel(link.getName());
                            List<Node> node = getNode(link.getNodeHead(),link.getNodeTail(), project);
                            node.get(0).setName(link.getNodeHeadName());
                            node.get(1).setName(link.getNodeTailName());
                            link.setTargetNode(node.get(0));
                            link.setSourceNode(node.get(1));
                            basicNetWork.addLink(link);
                            //设置线路口端口信息
                            //默认一条链路占用10个端口
                                if (portsMap.containsKey(link.getSourceNode().getId())) {
                                    for (int i = 0; i <10 ; i++) {
                                        basicNetWork.getPorts().get(link.getSourceNode().getId()).add(new BasicNetWork.PortL("LinkPort", "free", link));
                                    }
                                } else {
                                    portsMap.put(link.getSourceNode().getId(), new ArrayList<>());
                                }
                                if (portsMap.containsKey(link.getTargetNode().getId())) {
                                    for (int i = 0; i < 10; i++) {
                                        basicNetWork.getPorts().get(link.getTargetNode().getId()).add(new BasicNetWork.PortL("LinkPort", "free", link));
                                    }
                                } else {
                                    portsMap.put(link.getTargetNode().getId(), new ArrayList<>());
                                }

                        }
                        // 成功的集合
                        successList.add(new AddLinkDto(link, "添加成功"));
                    } catch (Exception e) {
                        List<Node> node = getNode(link.getNodeHead(),link.getNodeTail(), project);
                        node.get(0).setName(link.getNodeHeadName());
                        node.get(1).setName(link.getNodeTailName());
                        link.setTargetNode(node.get(0));
                        link.setSourceNode(node.get(1));
                        // 失败的集合
                        failList.add(new AddLinkDto(link, e.getMessage()));
                    }
                } // end for for (BasicNetWork.BasicLink link : links) {
            }
            // 更新网络信息
            updateProject(project);
        }
        // 返回操作
        Map<String, List<AddLinkDto>> res = new HashMap<>();
        res.put(successListKey, successList);
        res.put(failListKey, failList);
        // return ok
        return res;
    }


    //下载fiber数据

    @Override
    public Object downloadFiberDataFromProject(UserDto userDto, HttpServletRequest request,
                                               HttpServletResponse response, String pId) throws BaseException {
        LocalVerify.verifyString(pId, "项目ID");
        // 获取到项目的数据信息
       // userDto=userInfo.getCurrentOptUser();
        Project project = ProjectFactory.getObjectFromFile(pId, ProjectFactory.storePath);
        BasicNetWork netWork = project.getBasicNetWork();
        List<BasicNetWork.BasicLink> links = null;
        if (netWork != null && null != netWork.getFiberLinks() && netWork.getFiberLinks().size() > 0) {
            links = netWork.getFiberLinks();
        } else {
            links = Collections.singletonList(this.getBlankFiberLink());
        }
        // 下载数据信息
        downLoadExcel( request, response, links,
                project.getName() + "_Fiber链路数据", "Sheet1");
        return InitConstants.OK_MESSAGE;
    }

    private IBasicNetWork.FiberLink getBlankFiberLink() {
        return new IBasicNetWork.FiberLink();
    }
    private IBasicNetWork.WdmLink getBlankWdmLink() {
            return new IBasicNetWork.WdmLink();
    }

    private IBasicNetWork.OtnLink getBlankOtnLink() {
        return new IBasicNetWork.OtnLink();
    }
    private IBasicNetWork.SdhLink getBlankSdhLink() {
        return new IBasicNetWork.SdhLink();
    }

    @Override
    public Object downloadWdmDataFromProject(HttpServletRequest request, HttpServletResponse response, String pId) throws BaseException {
        LocalVerify.verifyString(pId, "项目ID");
        // 获取到项目的数据信息
        // userDto=userInfo.getCurrentOptUser();
        Project project = ProjectFactory.getObjectFromFile(pId, ProjectFactory.storePath);

        BasicNetWork netWork = project.getBasicNetWork();
        List<BasicNetWork.BasicLink> links = null;
        if (netWork != null && null != netWork.getWdmLinks() && netWork.getWdmLinks().size() > 0) {
            links = netWork.getWdmLinks();
        } else {
            links = Collections.singletonList(this.getBlankWdmLink());
        }

        // 下载数据信息
        downLoadExcel( request, response, links,
                project.getName() + "_Wdm链路数据", "Sheet1");
        return InitConstants.OK_MESSAGE;
    }

    @Override
    public Object downloadOtnDataFromProject(HttpServletRequest request, HttpServletResponse response, String pId) throws BaseException {
        LocalVerify.verifyString(pId, "项目ID");
        // 获取到项目的数据信息
        // userDto=userInfo.getCurrentOptUser();
        Project project = ProjectFactory.getObjectFromFile(pId, ProjectFactory.storePath);

        BasicNetWork netWork = project.getBasicNetWork();
        List<BasicNetWork.BasicLink> links = null;
        if (netWork != null && null != netWork.getOtnLinks() && netWork.getOtnLinks().size() > 0) {
            links = netWork.getOtnLinks();
        } else {
            links = Collections.singletonList(this.getBlankOtnLink());
        }

        // 下载数据信息
        downLoadExcel( request, response, links,
                project.getName() + "_Otn链路数据", "Sheet1");
        return InitConstants.OK_MESSAGE;
    }

    @Override
    public Object downloadSdhDataFromProject(HttpServletRequest request, HttpServletResponse response, String pId) throws BaseException {
        LocalVerify.verifyString(pId, "项目ID");
        // 获取到项目的数据信息
        // userDto=userInfo.getCurrentOptUser();
        Project project = ProjectFactory.getObjectFromFile(pId, ProjectFactory.storePath);
        BasicNetWork netWork = project.getBasicNetWork();
        List<BasicNetWork.BasicLink> links = null;
        if (netWork != null && null != netWork.getSdhLinks() && netWork.getSdhLinks().size() > 0) {
            links = netWork.getSdhLinks();
        } else {
            links = Collections.singletonList(this.getBlankSdhLink());
        }


        // 下载数据信息
        downLoadExcel( request, response, links,
                project.getName() + "_Sdh链路数据", "Sheet1");
        return InitConstants.OK_MESSAGE;
    }

    @Override
    public Object downLoadNeedServices(UserDto userDto, HttpServletRequest request, HttpServletResponse response, String pId) throws BaseException {
        Project project = ProjectFactory.getObjectFromFile(pId, ProjectFactory.storePath);
        List<DemandReportService> demandReportServices= project.getDemandList();

        downLoadExcel(request, response, demandReportServices, "业务数据", "Sheet1");
        return InitConstants.OK_MESSAGE;
    }

    @Override
    public Object downloadNode(UserDto userDto, HttpServletRequest request, HttpServletResponse response, String pId)throws BaseException {
        Project project = ProjectFactory.getObjectFromFile(pId, ProjectFactory.storePath);
        List<IBasicNetWork.BasicNode> nodeList = project.getBasicNetWork().getNodeList();
        downLoadExcel(request,response,nodeList,"节点数据","sheet1");
        return InitConstants.OK_MESSAGE;

    }

    @Override
    public Object downLoadPlanResult(UserDto userDto, HttpServletRequest request, HttpServletResponse response, String pId) throws BaseException {
        Project project = ProjectFactory.getObjectFromFile(pId, ProjectFactory.storePath);
        List<DemandReportService> demandReportServices= project.getDemandList();
        downLoadExcel(request, response, demandReportServices, "规划结果", "Sheet1");
        return InitConstants.OK_MESSAGE;
    }


    @Data
    class AddNodeDto implements Serializable {
        private static final long serialVersionUID = -5237463257289771638L;
        private IBasicNetWork.BasicNode node;
        private String reason;

        public AddNodeDto(IBasicNetWork.BasicNode node, String reason) {
            this.node = node;
            this.reason = reason;
        }
    }

    @Data
    class AddFiberLinkDto implements Serializable {
        private static final long serialVersionUID = 3177383509814403925L;
        private FiberLinkDto link;
        private String reason;

        public AddFiberLinkDto(FiberLinkDto link, String reason) {
            this.link = link;
            this.reason = reason;
        }
    }

    @Data
    class AddWdmLinkDto implements Serializable {
        private static final long serialVersionUID = 3177383509814403925L;
        private WdmLinkDto link;
        private String reason;

        public AddWdmLinkDto(WdmLinkDto link, String reason) {
            this.link = link;
            this.reason = reason;
        }
    }

    @Data
    class AddOtnLinkDto implements Serializable {
        private static final long serialVersionUID = 3177383509814403925L;
        private OtnLinkDto link;
        private String reason;

        public AddOtnLinkDto(OtnLinkDto link, String reason) {
            this.link = link;
            this.reason = reason;
        }
    }

    @Data
    class AddSdhLinkDto implements Serializable {
        private static final long serialVersionUID = 3177383509814403925L;
        private SdhLinkDto link;
        private String reason;

        public AddSdhLinkDto(SdhLinkDto link, String reason) {
            this.link = link;
            this.reason = reason;
        }
    }

    @Data
   class AddServiceDto implements Serializable{
        private static final long serialVersionUID = 3177383509814403935L;
        private ServiceDto service;
        private String Reason;

        public AddServiceDto(ServiceDto service, String reason) {
            this.service = service;
            Reason = reason;
        }
    }

    static Double getRateByRateStr(String rateStr) {
        if (null == rateStr || "".equals(rateStr)) return null;
        switch (rateStr) {
            case "155M":
                return 0.125;
            case "622M":
                return 0.5;
            case "GE":
                return 1.0;
            case "2.5G":
                return 2.5;
            case "10G":
                return 10.0;
            case "40G":
                return 40.0;
            case "100G":
                return 100.0;
            default: {
                return 0.0;
            }
        }
    }

    @Data
    class AddLinkDto implements Serializable {
        private static final long serialVersionUID = 3177383509814403925L;
        private IBasicNetWork.BasicLink link;
        private String reason;

        public AddLinkDto(IBasicNetWork.BasicLink link, String reason) {
            this.link = link;
            this.reason = reason;
        }
    }

    private void updateProject(Project project) throws BaseException {
        boolean b = ProjectFactory.saveObjectDataToFile(project, project.getId(), ProjectFactory.storePath);
        if (!b) throw new BaseException("文件固化失败");
    }

    private List<Node> getNode(String sourceNodeId,String targetNodeId,Project project){
        List<Node> nodeList = new ArrayList<>();
        IBasicNetWork.BasicNode fromNode = project.searchNodeById(sourceNodeId);
        IBasicNetWork.BasicNode toNode = project.searchNodeById(targetNodeId);
       Node node1=new Node();
       Node node2=new Node();
        if(fromNode!=null){
            node1.update(fromNode.getNodeId(),fromNode.getName(),fromNode.getPointX(),fromNode.getPointY());
        }
        if(toNode!=null){
             node2.update(toNode.getNodeId(), toNode.getName(), toNode.getPointX(), toNode.getPointY());
        }
        nodeList.add(node1);
        nodeList.add(node2);
        return nodeList;
    }
    @Data
    class FiberDto implements Serializable {
        private static final long serialVersionUID = 3177383509314403925L;
        private FiberLinkDto link;
        private String reason;

        public FiberDto(FiberLinkDto link, String reason) {
            this.link = link;
            this.reason = reason;
        }
    }

    @Data
    class WdmDto implements Serializable {
        private static final long serialVersionUID = 3177383509314403925L;
        private WdmLinkDto link;
        private String reason;

        public WdmDto(WdmLinkDto link, String reason) {
            this.link = link;
            this.reason = reason;
        }
    }

    @Data
    class OtnDto implements Serializable {
        private static final long serialVersionUID = 3177383509314403975L;
        private OtnLinkDto link;
        private String reason;

        public OtnDto(OtnLinkDto link, String reason) {
            this.link = link;
            this.reason = reason;
        }
    }

    @Data
    class SdhDto implements Serializable {
        private static final long serialVersionUID = 3127383509314413925L;
        private SdhLinkDto link;
        private String reason;

        public SdhDto(SdhLinkDto link, String reason) {
            this.link = link;
            this.reason = reason;
        }
    }

    @Data
    class BasicNodeDto implements Serializable {
        private static final long serialVersionUID = 3127383509314413925L;
        private NodeDto nodeDto;
        private String reason;

        public BasicNodeDto(NodeDto nodeDto, String reason) {
            this.nodeDto = nodeDto;
            this.reason = reason;
        }
    }


    @Autowired
    private TbAlgorithms tbAlgorithms;

    //添加wdm\otn\sdh时，对fiber的判断和修改,使用最小跳算法找到他们承载在fiber上的的层间路由
    private boolean addOperationBaseIsFiber(BasicNetWork netWork, BasicNetWork.BasicLink onLink) throws BaseException {
        String strategy="HOP";
        Set<BasicNetWork.BasicLink> links = new HashSet<>();
        for (BasicNetWork.BasicLink basicLink : netWork.getFiberLinks()) {
            links.add(basicLink);
        }
        //利用层间路由算法,找出承载的光缆网层间路由
        List<BasicNetWork.BasicLink> fiberLinks =tbAlgorithms.findNoMust(links,new HashSet<>(netWork.getNodeList()),
                netWork.getNodeMap().get(onLink.getNodeHead()), netWork.getNodeMap().get(onLink.getNodeTail()),strategy,netWork);
        List<String> fiberLinkIds = new ArrayList<>();
        List<String> fiberLinkNames=new ArrayList<>();

        if (fiberLinks == null || fiberLinks.isEmpty()) {
            throw new BaseException("找不到可承载的资源足够的底层链路，添加失败");
        } else {
            for (BasicNetWork.BasicLink basicLink : fiberLinks) {
                fiberLinkIds.add(basicLink.getId());
                fiberLinkNames.add(basicLink.getName());
            }
        }
        //将底层路由的id和链路信息加载到wdm中
        onLink.setBaseLinkIds(fiberLinkIds);
        onLink.setBaseLinks(fiberLinks);
        onLink.setBaseLinkNames(fiberLinkNames);
        return true;
    }

    //当链路是sdh/otn时找到承载它的wdm层间路由
    private boolean addOperationBaseIsWdm(BasicNetWork netWork, BasicNetWork.BasicLink onLink) throws BaseException {
        String strategy="HOP";
        Set<BasicNetWork.BasicLink> links = new HashSet<>();
        for (BasicNetWork.BasicLink basicLink : netWork.getWdmLinks()) {
            links.add(basicLink);
        }
        //利用层间路由算法,找出承载sdh的WDM链路的层间路由
        List<BasicNetWork.BasicLink> wdmLinks =tbAlgorithms.findNoMust(links,new HashSet<>(netWork.getNodeList()),
                netWork.getNodeMap().get(onLink.getNodeHead()), netWork.getNodeMap().get(onLink.getNodeTail()),strategy,netWork);
        List<String> wdmLinkIds = new ArrayList<>();
        List<String> wdmLinkNames=new ArrayList<>();

        if (wdmLinks == null || wdmLinks.isEmpty()) {
            throw new BaseException("找不到可承载的资源足够的底层链路，添加失败");
        } else {
            for (BasicNetWork.BasicLink basicLink : wdmLinks) {
                wdmLinkIds.add(basicLink.getId());
                wdmLinkNames.add(basicLink.getName());
            }
        }
        //将底层路由的id和链路信息加载到sdh中
        onLink.setBaseLinkIds(wdmLinkIds);
        onLink.setBaseLinks(wdmLinks);
        onLink.setBaseLinkNames(wdmLinkNames);
        return true;
    }

    //当链路是sdh时，找到承载它的otn路由
    private boolean addOperationBaseIsOtn(BasicNetWork netWork, BasicNetWork.BasicLink sdhLink) throws BaseException {
        String strategy="HOP";
        Set<BasicNetWork.BasicLink> links = new HashSet<>();
        for (BasicNetWork.BasicLink basicLink : netWork.getOtnLinks()) {
            links.add(basicLink);
        }
        //利用层间路由算法,找出承载sdh的otn链路的层间路由
        List<BasicNetWork.BasicLink> otnLinks =tbAlgorithms.findNoMust(links,new HashSet<>(netWork.getNodeList()),
                netWork.getNodeMap().get(sdhLink.getNodeHead()), netWork.getNodeMap().get(sdhLink.getNodeTail()),strategy,netWork);
        List<String> otnLinkIds = new ArrayList<>();
        List<String> otnLinkNames=new ArrayList<>();

        if (otnLinks == null || otnLinks.isEmpty()) {
            throw new BaseException("找不到可承载的资源足够的底层链路，添加失败");
        } else {
            for (BasicNetWork.BasicLink basicLink : otnLinks) {
                otnLinkIds.add(basicLink.getId());
                otnLinkNames.add(basicLink.getName());
            }
        }
        //将底层路由的id和链路信息加载到sdh中
        sdhLink.setBaseLinkIds(otnLinkIds);
        sdhLink.setBaseLinks(otnLinks);
        sdhLink.setBaseLinkNames(otnLinkNames);
        return true;
    }


}
